package com.example.lab.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.example.lab.entity.Permissions;
import com.example.lab.entity.Role;
import com.example.lab.entity.User;
import com.example.lab.entity.UserRoles;
import com.example.lab.mapper.RoleMapper;
import com.example.lab.mapper.UserMapper;
import com.example.lab.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.security.Permission;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户基础信息表 服务实现类
 * </p>
 *
 * @author 布莱恩
 * @since 2025-06-15
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService, UserDetailsService {

    private final UserMapper userMapper;
    private final RoleMapper roleMapper;

    /**
     * 根据用户名加载用户详情
     * 此方法是Spring Security框架要求实现的方法，用于根据用户名获取用户信息
     * 它主要用于认证和授权过程
     *
     * @param username 用户名，用于查询用户信息
     * @return UserDetails对象，包含用户信息
     * @throws UsernameNotFoundException 如果用户不存在，则抛出此异常
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 创建查询条件，用于根据用户名查询用户
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username);
        // 执行查询，获取用户信息
        User user = userMapper.selectOne(queryWrapper);

        // 如果用户不存在，抛出异常
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在");
        }

        // 查询并设置用户的角色信息
        List<Role> roles = userMapper.findRolesByUserId(user.getUserId());
        user.setRoles(roles);

        // 返回用户信息
        return user;
    }

    /**
     * 根据用户名获取用户信息
     * @param username
     * @return
     */
    @Override
    public User getUserByUsername(String username) {

        User user = userMapper.selectByUsername(username);
        user.setPassword("******");
        return user;
    }

    @Override
    public List<Role> getUserRoles(Integer userId) {
        return userMapper.selectRolesByUserId(userId);
    }

    @Override
    public boolean removeUserRoles(Integer userId) {
        return userMapper.deleteUserRolesByUserId(userId) >= 0;
    }

    @Override
    public User getUserWithRolesAndPermissions(String username) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username);
        User user = this.getOne(queryWrapper);

        if (user != null) {
            List<Role> roles = userMapper.selectRolesByUserId(user.getUserId());
            if (CollectionUtils.isNotEmpty(roles)) {
                roles.forEach(role -> {
                    List<Permissions> permissions = roleMapper.selectPermissionsByRoleId(role.getRoleId());
                    role.setPermissions(permissions);
                });
            }
            user.setRoles(roles);
        }

        return user;
    }

    @Override
    public boolean assignRolesToUser(Integer userId, List<Integer> roleIds) {
        // 先删除用户原有角色
        this.removeUserRoles(userId);

        // 添加新角色
        if (CollectionUtils.isNotEmpty(roleIds)) {
            List<UserRoles> userRoles = roleIds.stream()
                    .map(roleId -> {
                        UserRoles userRole = new UserRoles();
                        userRole.setUserId(userId);
                        userRole.setRoleId(roleId);
                        return userRole;
                    })
                    .collect(Collectors.toList());

            return userMapper.batchInsertUserRoles(userRoles) > 0;
        }

        return true;
    }

    @Override
    public boolean hasPermission(Integer userId, String permissionCode) {
        List<Permissions> permissions = userMapper.selectPermissionsByUserId(userId);
        return permissions.stream()
                .anyMatch(p -> permissionCode.equals(p.getPermissionCode()));
    }
}
